﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using libCommonClass;
using System.Runtime.InteropServices;
using libInterface;
using DrawingScreen.Messages;
using DrawingScreen.Constant;
using Org.Vesic.WinForms;
using System.Xml;
using System.IO;

namespace DrawingScreen
{
    public partial class FormBackground : Form
    {
        #region Platform Invoke

        /// <summary>
        /// CreateCompatibleDC
        /// </summary>
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr CreateCompatibleDC(IntPtr hDC);

        /// <summary>
        /// DeleteDC
        /// </summary>
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern bool DeleteDC(IntPtr hdc);

        /// <summary>
        /// SelectObject
        /// </summary>
        [DllImport("gdi32.dll", ExactSpelling = true)]
        public static extern IntPtr SelectObject(IntPtr hDC, IntPtr hObject);

        /// <summary>
        /// GetObject
        /// </summary>
        [DllImport("gdi32.dll")]
        static extern int GetObject(IntPtr hgdiobj, int cbBuffer, IntPtr lpvObject);

        /// <summary>
        /// DeleteObject
        /// </summary>
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern bool DeleteObject(IntPtr hObject);

        /// <summary>
        /// CreateCompatibleBitmap
        /// </summary>
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        public static extern IntPtr CreateCompatibleBitmap(IntPtr hObject, int width, int height);

        /// <summary>
        /// SetBkColor
        /// </summary>
        [DllImport("gdi32.dll", ExactSpelling = true, SetLastError = true)]
        static extern uint SetBkColor(IntPtr hdc, int crColor);

        /// <summary>
        /// SetTextColor
        /// </summary>
        [DllImport("gdi32.dll")]
        static extern uint SetTextColor(IntPtr hdc, int crColor);

        [DllImport("gdi32.dll")]
        private static extern bool BitBlt(
            IntPtr hdcDest, // handle to dstination DC
            int nXDest,  // x-coord of destination upper-left corner
            int nYDest,  // y-coord of destination upper-left corner
            int nWidth,  // width of destination rectangle
            int nHeight, // height of destination rectangle
            IntPtr hdcSrc,  // handle to source DC
            int nXSrc,   // x-coordinate of source upper-left corner
            int nYSrc,   // y-coordinate of source upper-left corner
            System.Int32 dwRop  // raster operation code
            );

        public enum TernaryRasterOperations
        {
            SRCCOPY = 0x00CC0020,
            SRCPAINT = 0x00EE0086,
            SRCAND = 0x008800C6,
            SRCINVERT = 0x00660046,
            SRCERASE = 0x00440328,
            NOTSRCCOPY = 0x00330008,
            NOTSRCERASE = 0x001100A6,
            MERGECOPY = 0x00C000CA,
            MERGEPAINT = 0x00BB0226,
            PATCOPY = 0x00F00021,
            PATPAINT = 0x00FB0A09,
            PATINVERT = 0x005A0049,
            DSTINVERT = 0x00550009,
            BLACKNESS = 0x00000042,
            WHITENESS = 0x00FF0062,
            CAPTUREBLT = 0x40000000 //only if WinVer >= 5.0.0 (see wingdi.h)
        }
        #endregion

        public FormBackground()
        {
            InitializeComponent();

            //Set the current resolution to Global.SCREEN_WIDTH, Global.SCREEN_HEIGHT
            Global.SCREEN_WIDTH = 845;
            Global.SCREEN_HEIGHT = 450;

            //Global.SCREEN_WIDTH = 1366;
            //Global.SCREEN_HEIGHT = 768;

            this.Width = Global.SCREEN_WIDTH;
            this.Height = Global.SCREEN_HEIGHT;

            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;

            //bmpElephant = new Bitmap(Properties.Resources.elephant, Global.SCREEN_WIDTH, Global.SCREEN_HEIGHT);

            bmpBackground = new Bitmap(Properties.Resources.bg_drawing_screen, Global.SCREEN_WIDTH, Global.SCREEN_HEIGHT);

            formState.Maximize(this);

            buildContent();

            bEnabled = true;

            ///////////////////////////////////////////////////////////
            Text = "Drawing Screen Program";

            m_menu = new ContextMenu();
            m_menu.MenuItems.Add(0,
                new MenuItem("Show", new System.EventHandler(Show_Click)));
            m_menu.MenuItems.Add(1,
                new MenuItem("Hide", new System.EventHandler(Hide_Click)));
            m_menu.MenuItems.Add(2,
                new MenuItem("Exit", new System.EventHandler(Exit_Click)));

            m_notifyicon = new NotifyIcon();
            m_notifyicon.Text = "Right click for context menu";
            m_notifyicon.Visible = true;
            m_notifyicon.Icon = Properties.Resources.serverIcon_drawingScreen;
            m_notifyicon.ContextMenu = m_menu;

            timer_invalidate.Interval = (int)((float)1000 / 5);
            timer_invalidate.Tick += new EventHandler(timer_invalidate_Tick);
            timer_invalidate.Enabled = true;
        }

        private Object bInvalidateLock = new Object();

        private bool _bInvalidate = false;

        public bool bInvalidate
        {
            get { 
                return _bInvalidate; 
            }
            set
            {
                lock (bInvalidateLock)
                {
                    _bInvalidate = value;
                }
            }
        }

        private void timer_invalidate_Tick(object sender, EventArgs e)
        {
            if (bInvalidate)
            {
                this.Invalidate();
                this.bInvalidate = false;
                //GC.Collect();
            }
        }

        public void HideTrayIcon()
        {
            m_notifyicon.Visible = false;
        }


        protected void Exit_Click(Object sender, System.EventArgs e)
        {
            this.Close();
        }
        protected void Hide_Click(Object sender, System.EventArgs e)
        {
            this.HideAndDiable();
        }
        protected void Show_Click(Object sender, System.EventArgs e)
        {
            this.ShowAndEnable();
        }

        private NotifyIcon m_notifyicon;
        private ContextMenu m_menu;

        private bool bEnabled = false;

        public void buildContent()
        {
            // Create string to draw.
            drawString = currentIndex.ToString();
            // Create font and brush.
            drawFont = new Font("Arial", 16);
            drawBrush = new SolidBrush(Color.Brown);
            // Create point for upper-left corner of drawing.
            x = this.Width - 50.0F;
            y = this.Height - 50.0F;
            // Set format of string.
            drawFormat = new StringFormat();
            drawFormat.FormatFlags = StringFormatFlags.DirectionRightToLeft;
        }

        public void ClearContentOnAllDrawingScreen()
        {
            for (int i = 0; i < drawingScreenList.Count; i++)
            {
                drawingScreenList[i].Clear();
            }

            drawingScreenList.Clear();

            SetDrawingScreen(currentIndex + 1);
        }

        private String drawString;
        private Font drawFont;
        private SolidBrush drawBrush;
        private float x;
        private float y;
        private StringFormat drawFormat;

        private List<CDrawingScreen> drawingScreenList = new List<CDrawingScreen>();

        private int currentIndex = 0;

        Bitmap view;
        Graphics viewGraphic;

        // Bitmap bmpElephant = null;
        Bitmap bmpBackground = null;

        public void SetDrawingScreen(int n)
        {
            drawingScreenList.Clear();

            for (int i = 0; i < n; i++)
            {
                drawingScreenList.Add(new CDrawingScreen());
            }
        }

        public void SetCurrentIndex(int slideIndex)
        {
            currentIndex = slideIndex;

            while (drawingScreenList.Count - 1 < currentIndex)
            {
                drawingScreenList.Add(new CDrawingScreen());
            }

            if (currentIndex >= 0 && currentIndex < drawingScreenList.Count)
            {
                drawingScreenList[currentIndex].UpdateClientState();
            }

            //this.Invalidate();
            this.bInvalidate = true;


        }

        private void FormBackground_Paint(object sender, PaintEventArgs e)
        {
            //return;

            Graphics g = e.Graphics;

            //view = (Bitmap)bmpElephant.Clone();

            //view = (Bitmap)bmpBackground.Clone();

            view = new Bitmap(Global.SCREEN_WIDTH, Global.SCREEN_HEIGHT);

            viewGraphic = Graphics.FromImage(view);

            if (currentIndex >= 0 && currentIndex <= drawingScreenList.Count - 1)
            {
                drawingScreenList[currentIndex].Draw(viewGraphic);
            }

            g.DrawImage(view, new Rectangle(0, 0, Global.SCREEN_WIDTH, Global.SCREEN_HEIGHT),
                new Rectangle(0, 0, view.Width, view.Height),
                 GraphicsUnit.Pixel);

            drawString = (currentIndex + 1).ToString();
            // Draw string to screen.
            e.Graphics.DrawString(drawString, drawFont, drawBrush, x, y, drawFormat);
        }

        public void ProcessMessage(CDrawingMessage message, IClientInfoProvider provider)
        {
            if (bEnabled == true)
            {
                if (currentIndex >= 0 && currentIndex <= drawingScreenList.Count - 1)
                {
                    drawingScreenList[currentIndex].ProcessMessage(message, provider);
                }

                if (message is CDrawingMessage_Clear_All_Slides)
                {
                    this.ClearContentOnAllDrawingScreen();
                }

                this.bInvalidate = true;
            }
        }

        public void ShowAndEnable()
        {
            this.Show();
            
            bEnabled = true;
        }

        public void HideAndDiable()
        {
            this.Hide();
            bEnabled = false;
        }

        private void FormBackground_Load(object sender, EventArgs e)
        {
            //view = Properties.Resources.elephant;
            //viewGraphic = Graphics.FromImage(view);

            this.SetDrawingScreen(1);
            this.SetCurrentIndex(0);
        }

        public void Next()
        {
            if (currentIndex < drawingScreenList.Count - 1)
            {
                currentIndex++;
            }
            else if (currentIndex == drawingScreenList.Count - 1)
            {
                drawingScreenList.Add(new CDrawingScreen());
                currentIndex++;
            }

            if (currentIndex >= 0 && currentIndex < drawingScreenList.Count)
            {
                drawingScreenList[currentIndex].UpdateClientState();
            }

            this.bInvalidate = true;
        }

        public void Prev()
        {
            if (currentIndex > 0)
            {
                currentIndex--;
            }

            if (currentIndex >= 0 && currentIndex < drawingScreenList.Count)
            {
                drawingScreenList[currentIndex].UpdateClientState();
            }

            this.bInvalidate = true;
        }

        FormState formState = new FormState();

        int dem = 0;

        private void FormBackground_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyData == Keys.M)
            {
                formState.Maximize(this);
            }
            else if (e.KeyData == Keys.R)
            {
                formState.Restore(this);
            }
            else if (e.KeyData == Keys.Z)
            {
                CDrawingMessage_ChangeColor cc = new CDrawingMessage_ChangeColor();
                cc.r = 255;
                cc.g = 0;
                cc.b = 0;

                this.ProcessMessage(cc, null);
            }
            else if (e.KeyData == Keys.X)
            {
                CDrawingMessage_ChangeColor cc = new CDrawingMessage_ChangeColor();
                cc.r = 0;
                cc.g = 255;
                cc.b = 0;

                this.ProcessMessage(cc, null);
            }
            else if (e.KeyData == Keys.C)
            {
                CDrawingMessage_ChangeColor cc = new CDrawingMessage_ChangeColor();
                cc.r = 0;
                cc.g = 0;
                cc.b = 255;

                this.ProcessMessage(cc, null);
            }
            else if (e.KeyData == Keys.A)
            {
                this.ProcessMessage(new CDrawingMessage_Line(), null);
            }
            else if (e.KeyData == Keys.S)
            {
                this.ProcessMessage(new CDrawingMessage_Freedom(), null);
            }
            else if (e.KeyData == Keys.D)
            {
                this.ProcessMessage(new CDrawingMessage_Circle(), null);
            }
            else if (e.KeyData == Keys.F)
            {
                this.ProcessMessage(new CDrawingMessage_Ellipse(), null);
            }
            else if (e.KeyData == Keys.G)
            {
                this.ProcessMessage(new CDrawingMessage_Rectangle(), null);
            }
            else if (e.KeyData == Keys.H)
            {
                CDrawingMessage_Pointer p = new CDrawingMessage_Pointer();
                p.ID = ((dem++) % 14);
                this.ProcessMessage(p, null);
            }
            else if (e.KeyData == Keys.J)
            {
                this.ProcessMessage(new CDrawingMessage_Clear(), null);
            }
            else if (e.KeyData == Keys.K)
            {
                CDrawingMessage_ClipArt ca = new CDrawingMessage_ClipArt();
                ca.ID = ((dem++) % 14);
                this.ProcessMessage(ca, null);
            }
            else if (e.KeyData == Keys.Q)
            {
                CDrawingMessage_ChangeWidth ct = new CDrawingMessage_ChangeWidth();
                ct.width = 1;
                this.ProcessMessage(ct, null);
            }
            else if (e.KeyData == Keys.W)
            {
                CDrawingMessage_ChangeWidth ct = new CDrawingMessage_ChangeWidth();
                ct.width = 5;
                this.ProcessMessage(ct, null);
            }
            else if (e.KeyData == Keys.E)
            {
                CDrawingMessage_ChangeWidth ct = new CDrawingMessage_ChangeWidth();
                ct.width = 10;
                this.ProcessMessage(ct, null);
            }
            else if (e.KeyData == Keys.Escape)
            {
                this.Close();
            }
            else if (e.KeyData == Keys.T)
            {
                this.Prev();
            }
            else if (e.KeyData == Keys.Y)
            {
                this.Next();
            }
            else if (e.KeyData == Keys.U)
            {
                this.ProcessMessage(new CDrawingMessage_Undo(), null);
            }
            else if (e.KeyData == Keys.I)
            {
                this.ProcessMessage(new CDrawingMessage_Redo(), null);
            }

            //this.Invalidate();
            //this.bInvalidate = true;
        }

        private bool isMouseDown = false;

        private void FormBackground_MouseDown(object sender, MouseEventArgs e)
        {
            isMouseDown = true;

            CDrawingMessage_Action action = new CDrawingMessage_Action();
            action.Action = CActionKind.TOUCH_DOWN;
            action.X = (double)e.X / Global.SCREEN_WIDTH;
            action.Y = (double)e.Y / Global.SCREEN_HEIGHT;

            this.ProcessMessage(action, null);

            //this.Invalidate();
        }

        private int old_x, old_y;

        private int count = 0;

        private void FormBackground_MouseMove(object sender, MouseEventArgs e)
        {
            if (isMouseDown == true)
            {
                if (old_x != e.X || old_y != e.Y)
                {
                    old_x = e.X;
                    old_y = e.Y;

                    CDrawingMessage_Action action = new CDrawingMessage_Action();
                    action.Action = CActionKind.TOUCH_MOVE;
                    action.X = (double)e.X / Global.SCREEN_WIDTH;
                    action.Y = (double)e.Y / Global.SCREEN_HEIGHT;

                    this.ProcessMessage(action, null);

                    //if (count < 4)
                    //{
                    //    count++;
                    //}
                    //else
                    //{
                    //    this.Invalidate();
                    //    count = 0;
                    //}

                }
            }
        }

        private void FormBackground_MouseUp(object sender, MouseEventArgs e)
        {

            CDrawingMessage_Action action = new CDrawingMessage_Action();
            action.Action = CActionKind.TOUCH_UP;
            action.X = (double)e.X / Global.SCREEN_WIDTH;
            action.Y = (double)e.Y / Global.SCREEN_HEIGHT;

            this.ProcessMessage(action, null);

            //this.Invalidate();

            isMouseDown = false;
        }

        private void FormBackground_SizeChanged(object sender, EventArgs e)
        {
            Global.SCREEN_HEIGHT = this.Height;
            Global.SCREEN_WIDTH = this.Width;

            // bmpElephant = new Bitmap(Properties.Resources.elephant, Global.SCREEN_WIDTH, Global.SCREEN_HEIGHT);
            bmpBackground = new Bitmap(Properties.Resources.bg_drawing_screen, Global.SCREEN_WIDTH, Global.SCREEN_HEIGHT);

            buildContent();

            //this.Invalidate();
            this.bInvalidate = true;
        }

        private void hideToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.HideAndDiable();
        }

        private void closeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void FormBackground_FormClosing(object sender, FormClosingEventArgs e)
        {
            this.HideTrayIcon();
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
             save("C:\\DrawingScsreenFiles\\save00.ds");

            //save("asdasdad\\dgsdfsaf@3##fsfasf~~~\\save00.ds");
            
            return;

            /*
            XmlDocument doc = new XmlDocument();

            XmlElement eleDrawingScreens = doc.CreateElement("DRAWING_SCREEN_S");
            doc.AppendChild(eleDrawingScreens);

            for (int i = 0; i < drawingScreenList.Count; i++)
            {
                XmlNode node = drawingScreenList[i].convertToXmlNode(doc, i);
                eleDrawingScreens.AppendChild(node);
            }

            doc.Save("C:\\save00.ds");*/
        }

        private void loadToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.load("C:\\DrawingScsreenFiles\\save00.ds");

            return;
            
            /*
            List<CDrawingScreen> dsList = new List<CDrawingScreen>();

            XmlDocument doc = new XmlDocument();
            doc.Load("c:\\myFile00.xml");

            XmlElement root = (XmlElement)doc.FirstChild;

            int count = root.ChildNodes.Count;

            for (int i = 0; i < count; i++)
            {
                XmlElement eleDrawingScreen = (XmlElement)root.ChildNodes[i];

                CDrawingScreen ds = CDrawingScreen.CreateDrawingScreen(eleDrawingScreen);

                dsList.Add(ds);
            }

            drawingScreenList = dsList;

            this.bInvalidate = true;*/
        }

        public bool load(string path)
        {
            try
            {
                List<CDrawingScreen> dsList = new List<CDrawingScreen>();

                XmlDocument doc = new XmlDocument();
                doc.Load(path);

                XmlElement root = (XmlElement)doc.FirstChild;

                int count = root.ChildNodes.Count;

                for (int i = 0; i < count; i++)
                {
                    XmlElement eleDrawingScreen = (XmlElement)root.ChildNodes[i];

                    CDrawingScreen ds = CDrawingScreen.CreateDrawingScreen(eleDrawingScreen);

                    dsList.Add(ds);
                }

                drawingScreenList = dsList;

                this.bInvalidate = true;

                return true;
            }
            catch
            {
                return false;
            }
        }

        public bool save(string Path)
        {
            try
            {
                DirectoryInfo di = Directory.GetParent(Path);
                if (!(di.Exists))
                { 
                    di.Create();
                }

                XmlDocument doc = new XmlDocument();

                XmlElement eleDrawingScreens = doc.CreateElement("DRAWING_SCREEN_S");
                doc.AppendChild(eleDrawingScreens);

                for (int i = 0; i < drawingScreenList.Count; i++)
                {
                    XmlNode node = drawingScreenList[i].convertToXmlNode(doc, i);
                    eleDrawingScreens.AppendChild(node);
                }

                doc.Save(Path);

                return true;
            }
            catch
            {
                return false;
            }
        }

        private void clearAllToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ClearContentOnAllDrawingScreen();

            this.bInvalidate = true;
        }
    }
}
